package com.textmanager.ui;

import com.textmanager.db.TextFileDAO;
import com.textmanager.model.TextFile;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.sql.SQLException;
import java.util.UUID;

public class TextEditorPanel extends JPanel {

    private static final String IMAGE_DATA_DIRECTORY = "imageData";

    private JTextPane textPane;
    private JToolBar toolBar;
    private TextFile currentFile;
    private JLabel fileNameLabel;

    public TextEditorPanel() {
        setLayout(new BorderLayout());
        initComponents();
        layoutComponents();
    }

    private void initComponents() {
        fileNameLabel = new JLabel(" "); // Initialize with a space to ensure it has a height
        fileNameLabel.setHorizontalAlignment(SwingConstants.CENTER);
        fileNameLabel.setOpaque(true);
        fileNameLabel.setBackground(new Color(210, 220, 230)); // Slightly different background for the label

        // Set background color for text area
        textPane = new JTextPane();
        textPane.setContentType("text/html"); // Set content type to HTML
        textPane.setBackground(new Color(245, 245, 250));
        textPane.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 14));
        // JTextPane handles word wrap differently, often via StyledDocument or by setting content type
        // For basic wrapping similar to JTextArea, we can set a content type that supports it or manage it manually.
        // For now, we'll rely on default JTextPane behavior which might not wrap words automatically without further configuration.

        // Set background color for toolbar
        toolBar = new JToolBar();
        toolBar.setFloatable(false);
        toolBar.setBackground(new Color(220, 230, 240));
        toolBar.setOpaque(true);

        JButton saveButton = new JButton("保存");
        saveButton.addActionListener(e -> saveFile());
        saveButton.setBackground(new Color(220, 230, 240));

        JButton insertImageButton = new JButton("插入图片");
        insertImageButton.addActionListener(e -> insertImage());
        insertImageButton.setBackground(new Color(220, 230, 240));

        toolBar.add(saveButton);
        toolBar.add(insertImageButton);

        // Add KeyListener to textPane for paste action
        textPane.addKeyListener(new java.awt.event.KeyAdapter() {
            @Override
            public void keyPressed(java.awt.event.KeyEvent e) {
                if ((e.getKeyCode() == java.awt.event.KeyEvent.VK_V) && ((e.getModifiersEx() & java.awt.event.InputEvent.CTRL_DOWN_MASK) != 0)) {
                    pasteImage();
                }
            }
        });
    }

    private void layoutComponents() {
        JPanel topPanel = new JPanel(new BorderLayout());
        topPanel.add(fileNameLabel, BorderLayout.NORTH);
        topPanel.add(toolBar, BorderLayout.CENTER);
        add(topPanel, BorderLayout.NORTH);
        add(new JScrollPane(textPane), BorderLayout.CENTER);
    }

    public void setEditorEnabled(boolean enabled) {
        textPane.setEditable(enabled);
        if (enabled) {
            textPane.setBackground(new Color(245, 245, 250)); // Original editable color
        } else {
            textPane.setBackground(new Color(230, 230, 230)); // Disabled/greyed-out color
        }
    }

    public void loadFile(TextFile file) {
        try {
            currentFile = TextFileDAO.getFile(file.getId());
            if (currentFile != null) {
                // When loading, we assume the content is HTML
                textPane.setText(currentFile.getContent()); 
                textPane.setCaretPosition(0);
                fileNameLabel.setText(currentFile.getName());
            } else {
                fileNameLabel.setText(" ");
            }
        } catch (SQLException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "加载文件失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void saveFile() {
        if (currentFile == null) {
            JOptionPane.showMessageDialog(this, "请先选择一个文件", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }

        try {
            // Use HTMLEditorKit to write the document content to a StringWriter.
            // This ensures that the HTML is generated in a way that JTextPane can correctly parse back.
            StringWriter writer = new StringWriter();
            HTMLEditorKit kit = (HTMLEditorKit) textPane.getEditorKit();
            HTMLDocument doc = (HTMLDocument) textPane.getDocument();
            kit.write(writer, doc, 0, doc.getLength());
            String htmlContent = writer.toString();

            currentFile.setContent(htmlContent);
            TextFileDAO.updateFile(currentFile);
            JOptionPane.showMessageDialog(this, "文件保存成功", "提示", JOptionPane.INFORMATION_MESSAGE);
        } catch (SQLException | IOException | javax.swing.text.BadLocationException e) { // Catch relevant exceptions
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "保存文件失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    public void clearEditor() {
        currentFile = null;
        textPane.setText("");
        fileNameLabel.setText(" ");
    }

    private void insertImage() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("Image files", "jpg", "jpeg", "png", "gif"));
        int returnValue = fileChooser.showOpenDialog(this);
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            java.io.File selectedFile = fileChooser.getSelectedFile();
            try {
                Path imagePath = saveImageToFile(selectedFile);
                String imageFileUrl = imagePath.toUri().toURL().toString();
                // Insert HTML <img> tag
                HTMLEditorKit kit = (HTMLEditorKit) textPane.getEditorKit();
                HTMLDocument doc = (HTMLDocument) textPane.getDocument();
                kit.insertHTML(doc, textPane.getCaretPosition(), "<img src='" + imageFileUrl + "'>", 0, 0, null);
            } catch (Exception e) { // Catch broader Exception for BadLocationException, IOException
                e.printStackTrace();
                JOptionPane.showMessageDialog(this, "插入图片失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private void pasteImage() { // This method is now called by the KeyListener
        // Check if clipboard contains image data before attempting to paste
        java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        if (!clipboard.isDataFlavorAvailable(java.awt.datatransfer.DataFlavor.imageFlavor)) {
            // If no image data, allow default paste behavior (e.g., text)
            // We can achieve this by not consuming the event or by explicitly calling textPane.paste()
            // For simplicity, we'll just return and let the default paste happen if it's not an image.
            // However, since we are manually handling Ctrl+V, we might need to explicitly call textPane.paste() for non-image content.
            // For now, this method will only handle image pasting.
            // To allow normal text paste, we might need to adjust the KeyListener logic or use ActionMap.
            // A simple approach for now: if it's not an image, do nothing here, assuming default paste might still work or needs separate handling.
            return; 
        }

        java.awt.datatransfer.Clipboard clipboard1 = Toolkit.getDefaultToolkit().getSystemClipboard();
        java.awt.datatransfer.Transferable transferable = clipboard1.getContents(null);
        if (transferable != null && transferable.isDataFlavorSupported(java.awt.datatransfer.DataFlavor.imageFlavor)) {
            try {
                Image image = (Image) transferable.getTransferData(java.awt.datatransfer.DataFlavor.imageFlavor);
                if (image != null) {
                    try {
                        Path imagePath = saveImageToFile(image);
                        String imageFileUrl = imagePath.toUri().toURL().toString();
                        // Insert HTML <img> tag
                        HTMLEditorKit kit = (HTMLEditorKit) textPane.getEditorKit();
                        HTMLDocument doc = (HTMLDocument) textPane.getDocument();
                        kit.insertHTML(doc, textPane.getCaretPosition(), "<img src='" + imageFileUrl + "'>", 0, 0, null);
                    } catch (Exception e) { // Catch broader Exception for BadLocationException, IOException
                        e.printStackTrace();
                        JOptionPane.showMessageDialog(this, "粘贴图片失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(this, "粘贴图片失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private Path getImageStorageDirectory() throws IOException {
        Path dirPath = Paths.get(IMAGE_DATA_DIRECTORY);
        if (!Files.exists(dirPath)) {
            Files.createDirectories(dirPath);
        }
        return dirPath;
    }

    private Path saveImageToFile(File imageFile) throws IOException {
        Path storageDir = getImageStorageDirectory();
        String extension = "";
        String fileName = imageFile.getName();
        int i = fileName.lastIndexOf('.');
        if (i > 0) {
            extension = fileName.substring(i);
        }
        String uniqueFileName = UUID.randomUUID().toString() + extension;
        Path destinationPath = storageDir.resolve(uniqueFileName);
        Files.copy(imageFile.toPath(), destinationPath, StandardCopyOption.REPLACE_EXISTING);
        return destinationPath.toAbsolutePath();
    }

    private Path saveImageToFile(Image image) throws IOException {
        Path storageDir = getImageStorageDirectory();
        String uniqueFileName = UUID.randomUUID().toString() + ".png"; // Assume PNG for pasted images
        Path destinationPath = storageDir.resolve(uniqueFileName);

        BufferedImage bufferedImage;
        if (image instanceof BufferedImage) {
            bufferedImage = (BufferedImage) image;
        } else {
            bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
            Graphics2D bGr = bufferedImage.createGraphics();
            bGr.drawImage(image, 0, 0, null);
            bGr.dispose();
        }
        ImageIO.write(bufferedImage, "png", destinationPath.toFile());
        return destinationPath.toAbsolutePath();
    }
}